#include <signal.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mosquitto.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#include "sqlite3.h"
#include "logger.h"
//#include "database.h"

#define ARRAY_SIZE(x)       (sizeof(x)/sizeof(x[0]))
#define MSG_MAX_SIZE        512
#define KEEP_ALIVE          60
#define FILE_NAME           "mqttsub.db"


int database_insert_data( char  *data);//存入数据库	

int g_stop = 0;
void sig_stop(int signum)//如果传的参数是信号1，SIGUSR1则停止循环
{
	if(SIGUSR1 == signum)
	{
		g_stop = 1;
	}
}
void message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *mesg)//objmosquitto new 中提供的数据
{
	log_info("%s\n", (char *)mesg->payload);
	
	if( database_insert_data((char *)mesg->payload)!=0)
	{
		log_error("database_insert_data() failure:%s\n", strerror(errno));
	}


}
void connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
	if(rc)//rc=0连接成功
	{
		log_error("connect failue\n");
	}
	else
	{
	
		log_info("call the function:connect_callback, connect successfully \n");
		if(mosquitto_subscribe(mosq, NULL, "temperature", 2) != MOSQ_ERR_SUCCESS)
		{
			log_info("mosquitto_subscribe() failure:%s\n", strerror(errno));
			exit(1);

		}
		log_info("mosquitto_subscribe() sucessfully\n");
	}

}

void disconnect_callback(struct mosquitto *mosq, void *obj, int result)
{
	log_warn("Call the function:disconnect_callback. waiting for the reconnection\n");
}

static inline void print_usage(char *progname)
{
	printf("Usage:%s [option]...\n", progname);
        printf("%s is a socket server program, which used to verify client and echo back string from it\n", progname);
	printf("\n Mandatory arguments to long options are mandatory for short options too:\n");
        printf("-b(daemon)set progname runing on background\n");
 	printf("-p(--port):sepcify server listen port.\n");
 	printf("-n(--hostname):sepcify host name.\n");
	printf("-h(--hellp):print this help information.\n");

	printf("\n Example:%s -b -p 8900\n", progname);
	return ;

}
int main(int argc, char **argv)
{
	int                      daemon_run=0;
	char                    *progname = NULL;
	int                      port;
	char                    *serv_ip;
	int                      opt;

        struct hostent          *hostentp=NULL;
	char                    *ip=NULL;
	char                    *hostname=NULL;
	char                     topic[15]="temperature";
	struct mosquitto        *mosq;
	int                      err;

	signal(SIGUSR1, sig_stop);//将sigusr1作为参数传给函数sig_stop

	struct option     long_options[] = 
	{

		{"dameon", no_argument, NULL, 'b'},
		{"port", required_argument, NULL, 'p'},
		{"help", no_argument, NULL, 'h'},
		{"hostname",required_argument, NULL, 'n'},
	
		{ NULL, 0, NULL, 0}

	};

	progname = basename(argv[0]);
                                                           

	while((opt = getopt_long(argc, argv,"bp:n:h", long_options, NULL)) != -1)//(需要参数再加:);
	{
		switch(opt)
		{
			case 'b':
				daemon_run=1;
				break;

		
			case 'p':
				port=atoi(optarg);//string -> int
				break;

			case 'n':
				hostname=optarg;
				break;

			case 'h':
				print_usage(progname);
				return EXIT_SUCCESS;

			default:
				break;
		}
	}

	if( !port )
	{
		print_usage(progname);
		return -1;
	}

	if(daemon_run)//设置程序背景运行
	{
		daemon(0, 0);
	}

        /*域名解析*/
#if 0
	if(hostname)
	{
		/*返回一个结构体指针*/
		
		
		hostentp=gethostbyname(hostname);//返回一个结构体指针
		if(hostentp==NULL)
		{
			log_error("get host by name %s\n", strerror(errno));
			return -2;
		}
		printf("hostname: %s\n", hostentp->h_name);
/*ntoa(),将网络字节序ip地址转换为字符串IP地址， in_addr结构体是一个32位的IPv4地址,hostentp->h_addr表示的是网络字节主机ip地址*/
		ip = inet_ntoa(*(struct in_addr *)hostentp->h_addr);
		printf("address: %s\n", ip);

	}

#endif

	if(logger_init("stdout", LOG_LEVEL_INFO) <0)
	{
		fprintf(stderr, "inital logger system failure:%s\n");	
		return -1;
	}


	mosquitto_lib_init();//使用mqtt的库函数前要先初始化


	mosq = mosquitto_new("subscript", true, NULL);//返回一个新的客户端,mosq句柄,obj回调参数

	if(mosq==NULL)
	{
		log_error("mosquitto_new() failure:%s\n", strerror(errno));
		goto cleanup;
		return -1;
	}
	log_info("mosquitto_new() sucessfully\n");

	
	mosquitto_username_pw_set(mosq,"lingyun", "iot@lingyun" );

        /*设置回调函数, 在收到订阅的消息后调用*/

	mosquitto_disconnect_callback_set(mosq, disconnect_callback );
	mosquitto_connect_callback_set(mosq, connect_callback );
	mosquitto_message_callback_set(mosq, message_callback );
	/*在回调函数里调用mosquitto_subscribe()*/


	if(mosquitto_connect(mosq, hostname, port, KEEP_ALIVE)!=MOSQ_ERR_SUCCESS)
	{
		log_warn("mosquitto_connect failure:%s\n", strerror(errno));
	}
	log_info("mosq connect() sucessfully\n");

	printf("-------------------------------------------------------------\n");
	err=mosquitto_loop_forever(mosq, -1, 1);
	if(err)/*功能：网络事件循环处理函数，通过创建新的线程不断调用mosquitto_loop() 函数处理网络事件，不阻塞*/
	{
		log_error("err=%d mosquitto_loop_forever()failure:%s\n", err, strerror(errno));
        goto cleanup;
		return -5;
	}	
cleanup:
	logger_term;
	mosquitto_destroy(mosq);//释放客户端，在用完mosq后执行
	mosquitto_lib_cleanup();
	return 0;
}


int database_insert_data( char  *data)//存入数据库	
{
	
        char          create[128];
	char          insert[128];
	sqlite3      *db;
        char         *errmsg;
	char	    **dbresult;
	int           row=0;
	int	      column=0;
	int           rv;
	char         *p=NULL;
	char         *data_num[2];
	char         *delim="/";
	int           i=0;
	float         temp_data;
	char         *p1;
	char          data_buff[64];

	memset(create, 0, sizeof(create));
        snprintf( create, sizeof(create), "create table if not exists mqttsub_pj (ID integer PRIMARY KEY, SN char(10), TIME char(50), TEMP char(10));");
	if(sqlite3_open(FILE_NAME, &db)!=0)
	{
		log_error("open()%s\n",errmsg);
		return -1;
	}


        if( sqlite3_exec(db, create, NULL, NULL, &errmsg)!=0)
	{
		log_error("create()%s\n",errmsg);
		sqlite3_close(db);
		return -2;
	}


	for(p = strtok(data, delim) ;p != NULL; p = strtok(NULL, delim))
        {
	
		data_num[i]=p;
		i++;
	}

	temp_data=atof(data_num[2]);

	memset(insert, 0, sizeof(insert));

	snprintf(insert, sizeof(insert), "insert into mqttsub_pj(SN, TIME, TEMP) values('%s', '%s', '%2.2f');", data_num[0], data_num[1], temp_data); 
    
	if(sqlite3_exec(db, insert, NULL, NULL, &errmsg)!= 0)
	{
	    	log_error("insert()%s\n", errmsg);
		return -3;
	}

	sqlite3_close(db);
	return 0 ;
}

